// https://segmentfault.com/a/1190000018429380

import { IDB } from '../db/index'
import { parseMsg } from './util'

const LOG_STORE_NAME = 'msg1'

export type Message = {
  idClient: string
  sessionId: string
  idServer: string
  from: string
  fromNick: string
  fromClientType: string
  fromDeviceId: string
  to: string
  time: number
  type: string
  text: string
  content: string
  userUpdateTime: number
  target: string
  status: string
  isHistoryable: boolean
  isRoamingable: boolean
  isSyncable: boolean
  isPushable: boolean
  isOfflinable: boolean
  isUnreadable: boolean
  isReplyMsg: boolean
  needPushNick: boolean
  needMsgReceipt: boolean
  isLocal: boolean
  resend: boolean
  scene: string
  callbackExt: string
  cc: boolean
  flow: string
}

export class DBServiceMsg1 {
  private idb: IDB

  constructor(idb: IDB) {
    this.idb = idb
  }

  getStore() {
    const iStore = this.idb.getStore(LOG_STORE_NAME)
    if (!iStore) throw new Error('DB not ready')
    return iStore
  }

  create(msg: Message) {
    const iStore = this.getStore()
    return iStore.create(msg)
  }

  bulkCreate(msgs: Message[]) {
    const iStore = this.getStore()
    return iStore.bulkCreate(msgs)
  }

  delete(id: string) {
    const iStore = this.getStore()
    return iStore.delete(id)
  }

  // 按 sessionId 和 time 组合的 sessionTime 来批量删除
  bulkDelete(options: { sessionId: string; timeStart: number; timeEnd: number }) {
    const iStore = this.getStore()
    return iStore.bulkDelete({
      keyName: 'sessionTime',
      lower: [options.sessionId, options.timeStart],
      upper: [options.sessionId, options.timeEnd]
    })
  }

  update(msg: Partial<Message>) {
    const iStore = this.getStore()
    return iStore.merge(msg)
  }

  read(id: string) {
    const iStore = this.getStore()
    return iStore.read(id)
  }

  readByIds(ids: string[]) {
    const iStore = this.getStore()
    return iStore.readByIds(ids)
  }
  bulkRead(options: { sessionId: string; timeStart: number; timeEnd: number; filter?: () => boolean }) {
    const iStore = this.getStore()
    return iStore.bulkRead({
      keyName: 'sessionTime',
      lower: [options.sessionId, options.timeStart],
      upper: [options.sessionId, options.timeEnd],
      filter: options.filter
    })
  }

  // 安全的读全表. 有脏数据会导致事务失败, 失败则递归调用
  async safeReadAll(
    offset = 0,
    limit = 1000,
    cb = (datas: any[]) => {
      // ...
    }
  ): Promise<void> {
    const iStore = this.getStore()
    const promiseArr = [iStore.readAllByPage(offset, limit)]
    for (; promiseArr.length > 0; ) {
      const promise = promiseArr.shift()
      try {
        const data = await promise
        if (data && data.count > 0) {
          console.log(`safeReadAll::current offset ${data.offset}, ready to next`)
          const msgs = this.msgToProperty(data.data as Message[])
          cb(msgs)
          promiseArr.push(iStore.readAllByPage(data.offset, limit))
        } else {
          console.log('safeReadAll::mission completed!')
        }
      } catch (err) {
        console.error('safeReadAll::failed', err)
        throw err
      }
    }
  }

  msgToProperty(datas: Message[]) {
    return datas.map((data) => {
      return parseMsg(data)
    })
  }
}
